package mlp.game.cherries;

import java.text.DecimalFormat;
import java.util.ArrayList;

import mlp.game.cherries.R;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Typeface;
import android.graphics.Paint.Align;
import android.graphics.Paint.Style;
import android.os.SystemClock;
import android.util.DisplayMetrics;
import android.view.MotionEvent;

import com.overkill.game.GameEngine;
import com.overkill.game.GameOptions;
import com.overkill.game.GameOverListener;
import com.overkill.game.RenderView;
import com.overkill.game.Sprite;

public class CherryEngine extends GameEngine {

	public static float GAME_SPEED = 1;
	private static float START_GAME_SPEED = 0;
	private static float MAX_GAME_SPEED = 0;
	private static float GAME_SPEED_MODIFIER = 0;
	private static float GAME_SPEED_PERCENT = 0;
	private static int PRE_GAME_TIME = 3;
	
	public static int GAME_SCORE = 10;
	public static int GAME_SCORE_FAIL = -5;
	
	Paint scoreText = new Paint();
	Paint scoreBoardFill = new Paint();
	Paint scoreBoardStroke = new Paint();
	Paint pauseTextBig = new Paint();
	Paint pauseTextSmall = new Paint();
	

	long gameStartTime;
	int gameRunTime;
	long gamePauseTime;
	
	int backgroundColor = 0xFFEDA887;
	int countdownLeft = 3;
	
	// Game objects
	Belt belt;
	Bitmap background;
	
	ArrayList<Cherry> cherries;
	Cherry draggedCherry = null;
	CherrySpawner cherrySpawner;
	
	int colors[] = new int[]{Color.RED, Color.YELLOW, Color.GREEN};
	Box boxes[] = new Box[3];
	
	DecimalFormat leadingZero = new DecimalFormat("00000");
	
	public CherryEngine(GameOptions options, GameOverListener gameOverListener, int targetFps){
		super(options, gameOverListener, targetFps);
	}

	@Override
	public void inizialize(Rect stage) {
		super.inizialize(stage);
				
		gamePaused = false;
		
		START_GAME_SPEED = dip(2.5f);
		MAX_GAME_SPEED = dip(15f);
		GAME_SPEED_MODIFIER = dip(0.0007f);
		
		GAME_SPEED = START_GAME_SPEED;
		GAME_SPEED_PERCENT = (GAME_SPEED - START_GAME_SPEED) / (MAX_GAME_SPEED - START_GAME_SPEED);
		
		GAME_SCORE = 10;
		
		countdownLeft = PRE_GAME_TIME;
		
		Sprite.debugPaint = new Paint();
		Sprite.debugPaint.setColor(Color.WHITE);
		Sprite.debugPaint.setStyle(Style.STROKE);
				
		// TODO create game objects
		belt = new Belt(new RectF(stage.left, stage.top + dip(50), stage.right, stage.bottom - dip(60)));
		background = BitmapFactory.decodeResource(getContext().getResources(), R.drawable.background);
		
		float boxWidth = dip(120);
		float totalSpace = stage.width() - boxWidth * boxes.length;
		float space = totalSpace / (boxes.length + 1);
						
		for(int i = 0; i < boxes.length; i++){
			boxes[i] = new Box(new RectF((boxWidth * i) + (space * (i+1)), -25, (space * (i+1)) + (boxWidth * (i+1)), dip(40)), colors[i]); 
		}		
		
		draggedCherry = null;
		cherries = new ArrayList<Cherry>();
		
		cherrySpawner = new CherrySpawner(belt, new Cherry[]{
				new Cherry(new Sprite(BitmapFactory.decodeResource(getContext().getResources(), R.drawable.cherry_red), 1, 1), Color.RED),
				new Cherry(new Sprite(BitmapFactory.decodeResource(getContext().getResources(), R.drawable.cherry_yellow), 1, 1), Color.YELLOW),
				new Cherry(new Sprite(BitmapFactory.decodeResource(getContext().getResources(), R.drawable.cherry_green), 1, 1), Color.GREEN)
		});
		
		// init score paint
		scoreText.setColor(Color.BLACK);
		scoreText.setTextAlign(Align.CENTER);
		scoreText.setTextSize(dip(18));
		Typeface celestia = Typeface.createFromAsset(getContext().getAssets(), RenderView.TYPEFACE_PATH);
		scoreText.setTypeface(celestia);
		scoreText.setAntiAlias(true);

		pauseTextBig = new Paint(scoreText);
		pauseTextBig.setTextSize(dip(40));
		pauseTextSmall = new Paint(scoreText);
		pauseTextSmall.setTextSize(dip(18));
		
		
		scoreBoardFill.setColor(0xCCFFFFFF);
		scoreBoardFill.setStyle(Style.FILL);
		scoreBoardStroke.setColor(0xCCF9B159);
		scoreBoardStroke.setStyle(Style.STROKE);
		scoreBoardStroke.setStrokeWidth(dip(3.3f));

		// Set game end time
		gameStartTime = SystemClock.elapsedRealtime() + countdownLeft * 1000;		
	}	
	
	@Override
	public void update(long gameTime, int deltaTime) {
		super.update(gameTime, deltaTime);
		
		gameRunTime = (int) ((gameTime - gameStartTime) / 1000);
		if (gamePaused == true)
			return;
		if (gameTime >= gameStartTime) {
			gameRunning = true;
		} else {
			countdownLeft = (int) ((gameStartTime - gameTime) / 1000);
		}
		if (gameRunning == false)
			return;		
		
		if(GAME_SPEED < MAX_GAME_SPEED){
			GAME_SPEED += GAME_SPEED_MODIFIER;
		}
		GAME_SPEED_PERCENT = (GAME_SPEED - START_GAME_SPEED) / (MAX_GAME_SPEED - START_GAME_SPEED);

		belt.update(gameTime);
		
		for(Box b : boxes){
			b.update(gameTime);
		}
		
		cherrySpawner.update(gameTime);
		cherrySpawner.spawn(cherries);
		
		ArrayList<Cherry> cherriesToRemove = new ArrayList<Cherry>();		
		for (Cherry c : cherries) {
			c.update(gameTime);
			if(c.isVisible() == false || c.getFrame().left > belt.getFrame().right){
				if(c.isVisible()){
					GAME_SCORE += GAME_SCORE_FAIL;
				}
				cherriesToRemove.add(c);
			}
		}
		cherries.removeAll(cherriesToRemove);
		if(GAME_SCORE <= 0){
			this.gameOver();
		}
	}
	
	@Override
	public void draw(Canvas canvas) {
		super.draw(canvas);
		// Draw Background		
		this.drawBackground(canvas);		
		// Draw Cherries
		for (Cherry c : cherries) {
			c.draw(canvas);
		}	
		// Draw score
		this.drawScore(canvas);		
		// Draw Pause screen
		if (gamePaused == true) {
			this.drawPauseScreen(canvas);
		}
		if (gameRunning == false) {
			this.drawCountDown(canvas);
		}
	}
	
	private void drawCountDown(Canvas canvas){
		canvas.drawText(getString(R.string.start_in, countdownLeft),
				getStage().width() / 2,
				getStage().height() / 2 - scoreText.getTextSize() / 2,
				pauseTextBig);
	}
	
	private void drawPauseScreen(Canvas canvas){
		int y = (int) (getStage().height() / 2 - pauseTextBig.getTextSize() / 2);
		canvas.drawText(getString(R.string.pause_pause),
				getStage().width() / 2, y, pauseTextBig);
		canvas.drawText(getString(R.string.pause_tabanywhere),
				getStage().width() / 2, (float) (y + pauseTextBig.getTextSize() / 2), pauseTextSmall);
	}
	
	private void drawBackground(Canvas canvas) {
		canvas.drawColor(backgroundColor);
		canvas.drawBitmap(background, 0, 0, null);
		belt.draw(canvas);
		for(int i = 0; i < boxes.length; i++){
			boxes[i].draw(canvas);
		}
	}

	private void drawScore(Canvas canvas) {
		RectF scoreRectF = new RectF(dip(325f), getStage().bottom - dip(50f), getStage().right - dip(5), getStage().bottom + 25);
		if(DEVICE_DENSITY < DisplayMetrics.DENSITY_TV)
			scoreRectF = new RectF(getStage().left + dip(5), getStage().bottom - dip(50f), getStage().right - dip(5), getStage().bottom + 25);
		canvas.drawRoundRect(scoreRectF, 20, 20, scoreBoardFill);
		canvas.drawRoundRect(scoreRectF, 20, 20, scoreBoardStroke);
		scoreText.setTextAlign(Align.LEFT);
		canvas.drawText("POINTS: " + leadingZero.format(GAME_SCORE),
							scoreRectF.left + dip(5),
							(float) (scoreRectF.top + scoreText.getTextSize() * 1.1),
							scoreText);
		canvas.drawText("TIME: " + leadingZero.format(gameRunTime) + " | SPEED: " + Math.round(GAME_SPEED_PERCENT * 100) + "%",
							scoreRectF.left + dip(5),
							(float) (scoreRectF.top + scoreText.getTextSize() * 2.1),
							scoreText);		
		scoreText.setTextAlign(Align.RIGHT);
	}
	
	@Override
	public void gameOver() {
		GameOptions options = new GameOptions();
		options.put("SCORE_SPEED_PERCENT", Math.round(GAME_SPEED_PERCENT * 100));
		options.put("SCORE_GAME_TIME", gameRunTime);
		super.gameOver(options);
	}
	
	@Override
	public void pauseGame() {
		gamePauseTime = SystemClock.elapsedRealtime();
		gamePaused = true;
		renderView.pauseRender(true);
	}

	@Override
	public void resumeGame() {
		long timeDiff = SystemClock.elapsedRealtime() - gamePauseTime;
		gameRunTime -= timeDiff;
		gamePaused = false;
		renderView.resumeRender();
	}
	
	@Override
	public void handleTouchEvent(int action, float x, float y){		
		if(action == MotionEvent.ACTION_DOWN && this.gamePaused){
			this.resumeGame();
		}	
		switch(action){
			case MotionEvent.ACTION_DOWN:
				// find cherry at x/y and mark it for dragging
				for (Box b : boxes) {
					b.setActive((draggedCherry != null) && b.isHit(draggedCherry));
				}
				for (Cherry c : cherries) {
					if(c.isHit(x, y) && draggedCherry == null && c.canBeDragged()){
						draggedCherry = c;
						draggedCherry.setDragged(true);
					}
				}
				break;
			case MotionEvent.ACTION_MOVE:
				// move current dragged cherry to x/y
				for (Box b : boxes) {
					b.setActive((draggedCherry != null) && b.isHit(draggedCherry));
				}
				if(draggedCherry != null)
					draggedCherry.moveTo(x - draggedCherry.getWidth() / 2, y - draggedCherry.getHeight() / 2);
				break;
			case MotionEvent.ACTION_UP:
				// check if cherry is over correct box, if not remove cherry
				for(int i = 0; i < boxes.length; i++){
					boxes[i].setActive(false);
				}
				if(draggedCherry != null){
					draggedCherry.setDragged(false);
					for (Box b : boxes) {
						if(b.isHit(draggedCherry)){
							//draggedCherry.setVisible(false);
							draggedCherry.setCanBeDragged(false);
							draggedCherry.dropped();
							if(draggedCherry.getColor() == b.getColor()){
								b.dropped();
								GAME_SCORE += 1;
							}else{
								GAME_SCORE += GAME_SCORE_FAIL;
							}
						}
					}
					if(belt.isHit(draggedCherry) == false && draggedCherry.canBeDragged()){ // Droped outside of belt
						draggedCherry.dropped();
//						draggedCherry.setVisible(false);		
						GAME_SCORE += GAME_SCORE_FAIL;				
					}
					draggedCherry = null;
				}
		}
	}
	
}
